using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using iSchema;

namespace AV
{

    public enum Importance { Debug, Info, Warning, Error, Fatal, No };

    /// <summary>
    /// Provides logging
    /// </summary>
    public class Log4cs
    {

        protected static string m_fileName = "Log_{0}.log";
        protected static string m_logsDir = @"c:\logs\";

        /// <summary>
        /// Name of log file. Use {0} to place date in file name, i.e. logs_{0}.log
        /// </summary>
        public static string FileName
        {
            get { return m_fileName; }
            set
            {
                if( !value.Contains("{0}") )
                    throw new FormatException("Log filename must contains '{0}'!");

                m_fileName = value;
            }
        }

        /// <summary>
        /// Gets/sets directory where logs are
        /// </summary>
        public static string Dir
        {
            get { return m_logsDir; }
            set
            {
                m_logsDir = value;
                if( !m_logsDir.EndsWith("\\") )
                    m_logsDir += "\\";
            }
        }


        /// <summary>
        /// Time in log file, set to "" if no time is needed
        /// </summary>
        public static string TimeFmt = "HH:mm:ss";

        /// <summary>
        /// Do we need to output to console
        /// </summary>
        public static bool OutputToConsole = false;

        public static void Log( string msg, params object[] Args )
        {
            Log(Importance.Info, msg, Args);
        }

        public static void Log( Importance logLevel, string msg, params object[] Args )
        {
            DirectoryInfo dirInfo = new DirectoryInfo(Dir);
            StringBuilder sb = new StringBuilder();
            StringBuilder strMsg = new StringBuilder();
            string filename = "";
            StreamWriter streamW = null;

            if( !dirInfo.Exists )
            {
                try
                {
                    dirInfo.Create();
                } catch( Exception )
                {
                    System.Console.WriteLine("Error creating '{0}' directory!", Dir);
                    return;
                }
            }  // END IF

            try
            {
                sb.AppendFormat(FileName, DateTime.Now.ToString("yyyyMMdd"));
                filename = dirInfo.FullName;

                if( !filename.EndsWith("\\") )         // Ensures that ends w/ '\'
                    filename += "\\";

                filename += sb.ToString();
                //            System.Console.WriteLine( "Log file name: " + filename );

            } catch( Exception )
            {
                System.Console.WriteLine("Bad log file name '{0}'!", FileName);
            }

            if( TimeFmt.Length > 0 )
                strMsg.Append(DateTime.Now.ToString(TimeFmt)).Append(" ");

            if( logLevel != Importance.No )
                strMsg.Append('[').Append(logLevel.ToString().ToUpper()).Append("] ");

            //strMsg += " " + msg + Environment.NewLine;
            strMsg.AppendFormat(msg, Args).Append(Environment.NewLine);

            if( OutputToConsole )
                System.Console.Write(strMsg.ToString());

            try
            {
                streamW = new StreamWriter(filename, true);
                streamW.Write(strMsg);
            } catch( Exception )
            {
                System.Console.WriteLine("Error writing to '{0}' file!", filename);
            }

            if( streamW != null )
                streamW.Close();
        }


    }

    /// <summary>
    /// Contains static usefull methods
    /// </summary>
    public class Common
    {

        /// <summary>
        /// Gets path of executable and ensures its ends w/ '\'
        /// </summary>
        public static string GetPath()
        {
            string aPath = "";
            try
            {
                System.Reflection.Module[] modules = System.Reflection.Assembly.GetExecutingAssembly().GetModules();
                aPath = System.IO.Path.GetDirectoryName(modules[0].FullyQualifiedName);
                if((aPath != "") && (aPath[aPath.Length - 1] != '\\')) aPath += '\\';
            } catch(Exception) { }

            return aPath;
        }

        /// <summary>
        /// Ensures that path to directories exists. Tries to create if no directory
        /// </summary>
        /// <param name="arPath">Array of directory to check for existance</param>
        public static bool EnsurePathExists(string[] arPath)
        {
            bool isOk = true;

            try
            {
                foreach(string path in arPath)
                {
                    if(!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                }
            } catch(Exception ex)
            {
                isOk = false;
                Log4cs.Log(Importance.Error, "Error ensuring directory existing!");
                Log4cs.Log(Importance.Debug, ex.ToString());
            }

            return isOk;
        }

        public static string CamelCaseIt( string name, bool makeFirstLower )
        {
            string ccName = "";

            if( !string.IsNullOrEmpty(name) )
            {
                string[] ar = name.Split(new char[] { '_' });
                for(int i = 0; i < ar.Length; i++)
                {
                    if( ar[i].Length > 0 )
                    {
                        // If first token should be lower case
                        if(makeFirstLower && (i == 0))
                        {
                            ccName = ar[i].ToLower();
                        } else
                        {
                            // Not enough length to be camel-cased
                            if(ar[i].Length == 1)
                            {
                                ccName += ar[i].ToUpper();
                            } else
                            {
                                ccName += ar[i].Substring(0, 1).ToUpper() + ar[i].Substring(1, ar[i].Length - 1).ToLower();
                            }
                        }
                    }
                }  // END FOR ( list all tokens )
            }
            return ccName;
        }

        /// <summary>
        /// Translates schema type name to native. (varchar => String)
        /// </summary>
        /// <param name="name"></param>
        /// <param name="schemaType"></param>
        /// <returns></returns>
        public static string GetNativeType(string name, int schemaType)
        {
            switch(name.ToLower())
            {
                case "integer":
                    return "int";
                case "varchar":
                    return "String";
                case "timestamp":
                    return "Date";
            }

            throw new ArgumentException("Unknown schema type [" + name + "]");
        }
    }

}
